package org.jeecg.modules.user.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xkcoding.http.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.jeecg.common.api.MemberAPI;
import org.jeecg.common.api.dto.MemberDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.constant.BikeConstant;
import org.jeecg.modules.param.member.entity.BikeMemberUser;
import org.jeecg.modules.param.member.mapper.BikeMemberUserMapper;
import org.jeecg.modules.param.spend.entity.BikeMemberUserSpend;
import org.jeecg.modules.param.spend.mapper.BikeMemberUserSpendMapper;
import org.jeecg.modules.user.code.entity.SmsCode;
import org.jeecg.modules.user.code.service.SmsCodeService;
import org.jeecg.modules.user.member.dto.*;
import org.jeecg.modules.user.member.entity.Member;
import org.jeecg.modules.user.member.mapper.MemberMapper;
import org.jeecg.modules.user.member.service.MemberService;
import org.jeecg.modules.utils.BikeResult;
import org.jeecg.modules.utils.CaculateDistanceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @Description: bike_pile
 * @Author: jeecg-boot
 * @Date: 2021-05-19
 * @Version: V1.0
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {


    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private BikeMemberUserMapper bikeMemberUserMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private MemberAPI memberAPI;

    @Autowired
    private SmsCodeService smsCodeService;

    @Resource
    private BikeMemberUserSpendMapper bikeMemberUserSpendMapper;

    @Value("${application.domain}")
    public String domain;

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    @Override
    public BikeResult insertMenberUser(Member member) {
        QueryWrapper qw = new QueryWrapper();
        qw.eq("phone", member.getPhone());
        qw.ne("status", "4");
        //查询用户是否已经注册
        Member mbr = memberMapper.selectOne(qw);
        if (mbr != null) {
            return BikeResult.error("0", "该用户已注册,请直接登陆！", null);
        }
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(member.getPhone());
        smsCode.setSmsCode(member.getSmsCode());
        smsCode.setType("1");
        //判断验证码是否失效
        BikeResult flag = smsCodeService.checkSmsCode(smsCode);
        if (flag.getCode().equals("200")) {
            String salt = oConvertUtils.randomGen(8);
//            String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
            String passwordEncode = PasswordUtil.encrypt(member.getPhone(), member.getPassword(), salt);
            member.setPassword(passwordEncode);
            member.setSalt(salt);
            member.setCode(member.getPhone());
            member.setStatus("1");
            member.setIsCertification("0");
            member.setIsSecretFree("0");
            member.setRegisterType("1");
//            member.setRideStatus("1");
            memberMapper.insert(member);
            return BikeResult.ok("1", "注册成功！", null);
        } else {
            return BikeResult.error("0", flag.getMessage(), null);
        }
    }

    @Override
    public BikeResult appLogin(LoginsReq loginsReq) {

        String syspassword = loginsReq.getPassWord();

        String username = loginsReq.getPhone();
        //获取其他app  token key
        boolean b1 = redisUtil.hasKey(CommonConstant.PREFIX_USER_TOKEN + username);
        if (b1) {
            String o = (String) redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + username);
            if (StringUtils.isNotEmpty(o)) {
                boolean b = redisUtil.hasKey(o);
                // TODO: 2021/9/28 月月鸟的单点登录
                if (b) {
                    redisUtil.del(o);
                }
            }
        }
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 1459 / 1000);
        //保存app ken key
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + username, CommonConstant.PREFIX_USER_TOKEN + token);

        QueryWrapper qw = new QueryWrapper();
        qw.eq("phone", loginsReq.getPhone());
        qw.ne("status", "4");
        //查询用户是否第一次登录
        Member member = memberMapper.selectOne(qw);
        //手机验证码登录
        if (member == null) {
            return BikeResult.error("0", "账号不存在", null);
        }
        String userpassword = PasswordUtil.encrypt(loginsReq.getPhone(), loginsReq.getPassWord(), member.getSalt());
        String spassword = member.getPassword();
        //检测账号是否异常  1正常2异常3黑名单4注销
        if (member.getStatus().equals("4")) {
            return BikeResult.error("0", "账号已注销,请联系客服！", null);
        } else if (!spassword.equals(userpassword)) {
            return BikeResult.error("0", "密码错误！", null);
        }

        String state = member.getIsCertification();
        member.setToken(token);
        if (state.equals("0")) {
            member.setRideStatus("1");  //未实名
        }

        member.setHeadIcon(domain + member.getHeadIcon());
        return BikeResult.ok("1", "登录成功!", member);

    }

    @Override
    public BikeResult phoneLogin(LoginPhoneReq loginPhoneReq) {
        if (StringUtil.isEmpty(loginPhoneReq.getPhone()) || loginPhoneReq.getPhone().length() != 11) {
            return BikeResult.error("0", "无效手机号！", null);
        }

        // 生成token


        QueryWrapper qw = new QueryWrapper();
        qw.eq("phone", loginPhoneReq.getPhone());
        qw.ne("status", "4");
        //查询用户是否第一次登录
        Member member = memberMapper.selectOne(qw);
        if (member == null) {
//            //第一次验证码直接登录，直接创建账户
//            m.setRegisterType("1");
//            m.setRegisterTime(new Date());
//            m.setPhone(loginPhoneReq.getPhone());
//            m.setPassword(MD5Utils.encrypt("123"));
//            m.setStatus("1");
//            memberMapper.insert(m);
            return BikeResult.error("0", "账号不存在", null);
        }
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(loginPhoneReq.getPhone());
        smsCode.setSmsCode(loginPhoneReq.getSmsCode());
        smsCode.setType("4");
        //判断验证码是否正确
        BikeResult bikeResult = smsCodeService.checkSmsCode(smsCode);
        if (bikeResult.getCode().equals(BikeConstant.y_n_no)) {
            return BikeResult.ok("0", "验证码错误!", null);
        }
        String syspassword = member.getPassword();
        String username = member.getPhone();
        String token = JwtUtil.sign(username, syspassword);
        //获取其他app  token key
        boolean b1 = redisUtil.hasKey(CommonConstant.PREFIX_USER_TOKEN + username);
        if (b1) {
            String o = (String) redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + username);
            //删除
            boolean b = redisUtil.hasKey(o);
            // TODO: 2021/9/28 月月鸟的单点登录
            if (b) {
                redisUtil.del(o);
            }
        }
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 1459 / 1000);
        //保存app token key
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + username, CommonConstant.PREFIX_USER_TOKEN + token);
        Member m = new Member();

        member.setToken(token);
        String state = member.getIsCertification();
        if (state.equals("0")) {
            member.setRideStatus("1");  //未实名
        }

        member.setHeadIcon(domain + member.getHeadIcon());
        return BikeResult.ok("1", "登录成功!", member);
    }

    @Override
    public BikeResult forgetPassword(ForgetPasswordReq forgetPasswordReq) {
        if (StringUtil.isEmpty(forgetPasswordReq.getPhone()) || forgetPasswordReq.getPhone().length() != 11) {
            return BikeResult.error("0", "无效手机号！", null);
        }
        QueryWrapper qw = new QueryWrapper();
        qw.eq("phone", forgetPasswordReq.getPhone());
        qw.ne("status", "4");
        //查询用户是否第一次登录
        Member member = memberMapper.selectOne(qw);
        if (member == null) {
            return BikeResult.error("0", "账号不存在", null);
        }
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(forgetPasswordReq.getPhone());
        smsCode.setSmsCode(forgetPasswordReq.getSmsCode());
        smsCode.setType("2");
        //判断验证码是否正确
        BikeResult bikeResult = smsCodeService.checkSmsCode(smsCode);
        if (!bikeResult.getCode().equals("200")) {
            return bikeResult;
        }
        String salt = oConvertUtils.randomGen(8);
        String userpassword = PasswordUtil.encrypt(forgetPasswordReq.getPhone(), forgetPasswordReq.getPassWord(), salt);
        Member me = new Member();
        me.setPhone(forgetPasswordReq.getPhone());
        me.setPassword(userpassword);
        me.setSalt(salt);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("phone", forgetPasswordReq.getPhone());
        int param = memberMapper.update(me, queryWrapper);
        if (param == 1) {
            return BikeResult.ok("1", "修改成功", param);
        }
        return BikeResult.error("0", "修改失败！", null);

    }

    @Override
    public BikeResult updateMember(MemberReq memberReq) {
        UpdateWrapper up = new UpdateWrapper();
        if (!StringUtil.isEmpty(memberReq.getHeadIcon())) {
            up.set(memberReq.getHeadIcon() != null && memberReq.getHeadIcon() != "", "head_icon", memberReq.getHeadIcon());
        }
        up.eq("id", memberReq.getId());
        int param = memberMapper.update(null, up);
        if (param != 1) {
            return BikeResult.ok("0", "修改失败！", param);
        }
        return BikeResult.ok("1", "修改成功！", param);
    }

    @Override
    public BikeResult checkPhone(LoginPhoneReq loginPhoneReq) {
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(loginPhoneReq.getPhone());
        smsCode.setSmsCode(loginPhoneReq.getSmsCode());
        smsCode.setType("5");
        //判断验证码是否正确
        BikeResult bikeResult = smsCodeService.checkSmsCode(smsCode);
        if (!bikeResult.getCode().equals("200")) {
            return BikeResult.ok(bikeResult.getCode(), bikeResult.getMessage(), false);
        } else {
            return BikeResult.ok("1", "成功", true);
        }


    }

    @Override
    public BikeResult updatePhone(LoginPhoneReq loginPhoneReq, HttpServletRequest request) {
        String accessToken = request.getHeader("X-Access-Token");
        // 解密获得username，用于和数据库进行对比
        String username = JwtUtil.getUsername(accessToken);
        MemberDTO m = memberAPI.getMember(username);
        if (loginPhoneReq.getPhone().equals(username)) {
            return BikeResult.ok("0", "更换手机号与原手机号码一致，无需修改！", null);
        }
        Integer selectCount = bikeMemberUserMapper.selectCount(new QueryWrapper<BikeMemberUser>().eq("code", loginPhoneReq.getPhone()).ne("status", "4"));
        if (selectCount != 0) {
            return BikeResult.ok("0", "手机号已被使用", null);
        }
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(loginPhoneReq.getPhone());
        smsCode.setSmsCode(loginPhoneReq.getSmsCode());
        smsCode.setType("5");
        //判断验证码是否正确
        BikeResult bikeResult = smsCodeService.checkSmsCode(smsCode);
        if (!bikeResult.getCode().equals("200")) {
            return BikeResult.ok(bikeResult.getCode(), bikeResult.getMessage(), false);
        } else {
            String salt = oConvertUtils.randomGen(8);
            String password = PasswordUtil.encrypt(loginPhoneReq.getPhone(), loginPhoneReq.getPassWord(), salt);
            Member member = new Member();
            member.setPhone(loginPhoneReq.getPhone());
            member.setId(m.getId());
            member.setPassword(password);
            member.setCode(loginPhoneReq.getPhone());
            member.setSalt(salt);
            memberMapper.updateById(member);
            return BikeResult.ok("1", "成功", true);
        }
    }

    @Override
    public BikeResult getTripList(MemberIdReq memberIdReq, HttpServletRequest request) {
        String accessToken = request.getHeader("X-Access-Token");
        // 解密获得username，用于和数据库进行对比
        String username = JwtUtil.getUsername(accessToken);
        MemberDTO member = memberAPI.getMember(username);
        Page<TripRes> page = new Page<>(memberIdReq.getPageNum(), memberIdReq.getPageSize());
        if (StringUtils.isNotEmpty(memberIdReq.getIsPay())) {
            if (memberIdReq.getIsPay().equals("0")) {
                memberIdReq.setRideStatus("4");
            }
        }
        memberIdReq.setUserId(member.getId());
        List<TripRes> result = memberMapper.getTripList(memberIdReq);
        for (TripRes tripRes : result) {
            if (StringUtils.isNotEmpty(tripRes.getLongitude1()) && StringUtils.isNotEmpty(tripRes.getLongitude2())) {
                //增加骑行距离
                GlobalCoordinates gps1 = new GlobalCoordinates(Double.parseDouble(tripRes.getLongitude1()), Double.parseDouble(tripRes.getLatitude1()));
                GlobalCoordinates gps2 = new GlobalCoordinates(Double.parseDouble(tripRes.getLongitude2()), Double.parseDouble(tripRes.getLatitude2()));
                double distance = CaculateDistanceUtils.getDistanceMeter(gps1, gps2, Ellipsoid.WGS84);
                tripRes.setDistance(distance);
            }
            if (StringUtils.isEmpty(tripRes.getLongitude2())) {
                tripRes.setLongitude2(tripRes.getLongitude1());
                tripRes.setLatitude2(tripRes.getLatitude1());
            }
            if (StringUtils.isNotEmpty(tripRes.getUseLong())) {
                int param = Integer.parseInt(tripRes.getUseLong()) * 1000;
                long days = param / (1000 * 60 * 60 * 24);
                long hours = (param - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
                long minutes = (param - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);
                if (days == 0 && hours == 0) {
                    tripRes.setUseLong(minutes + "分钟");
                } else if (days == 0) {
                    tripRes.setUseLong(hours + "小时" + minutes + "分钟");
                } else {
                    tripRes.setUseLong(days + "天" + hours + "小时" + minutes + "分钟");
                }
                //添加消费记录
                BikeMemberUserSpend bikeMemberUserSpend = bikeMemberUserSpendMapper.selectOne(new QueryWrapper<BikeMemberUserSpend>().eq("user_id", member.getId()).eq("order_id", tripRes.getId()));
                if (bikeMemberUserSpend != null) {
                    tripRes.setSpendType(bikeMemberUserSpend.getSpendType());
                }
            }
        }
        Page<TripRes> tripResPage = new Page<>(memberIdReq.getPageNum(), memberIdReq.getPageSize());
        tripResPage.setRecords(result);
        tripResPage.setTotal(result.size());
        return BikeResult.ok("1", "查询成功", tripResPage);
    }

    @Override
    public BikeResult appLogOut(HttpServletRequest request) {
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        if (oConvertUtils.isEmpty(token)) {
            return BikeResult.error("0", "退出登录失败！", null);
        }
        redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
        String username = JwtUtil.getUsername(token);
        MemberDTO member = memberAPI.getMember(username);
        String getui = BikeConstant.client_id_prefix + username+member.getCode();
        boolean b = redisUtil.hasKey(getui);
        if (b){
            redisUtil.del(getui);
        }
        return BikeResult.error("1", "退出登录成功！", null);
    }

    @Override
    public BikeResult appLogOff(HttpServletRequest request) {
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String username = JwtUtil.getUsername(token);
        MemberDTO member = memberAPI.getMember(username);
        Member meb = new Member();
        meb.setId(member.getId());
        meb.setStatus("4");
        int param = memberMapper.updateById(meb);
        if (param == 1) {
            return BikeResult.ok("1", "注销成功！", param);
        } else {
            return BikeResult.error("0", "注销失败！", param);
        }

    }

    @Override
    public BikeResult detailed(Integer pageNum, Integer pageSize, HttpServletRequest request) {
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String username = JwtUtil.getUsername(token);
        MemberDTO member = memberAPI.getMember(username);
        Page<DetauledRes> page = new Page<>(pageNum, pageSize);
        IPage<DetauledRes> result = memberMapper.detailed(page, member.getId());
        List<DetauledRes> records = result.getRecords();
        for (DetauledRes tb : records) {
            DecimalFormat format = new DecimalFormat("0.00");
            tb.setAmount(format.format(new BigDecimal(tb.getAmount())));
        }
        return BikeResult.ok("1", "成功", result);
    }

    @Override
    public BikeResult updatePassword(MemberPwdReq memberPwdReq, HttpServletRequest request) {
        BikeMemberUser bikeMemberUser = null;
        //查询用户是否第一次登录
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String phone = JwtUtil.getUsername(token);
        LambdaQueryWrapper<BikeMemberUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BikeMemberUser::getPhone, phone);
        bikeMemberUser = bikeMemberUserMapper.selectOne(queryWrapper);

        String passwordEncode = PasswordUtil.encrypt(phone, memberPwdReq.getUsedPassWord(), bikeMemberUser.getSalt());
        if (!bikeMemberUser.getPassword().equals(passwordEncode)) {
            return BikeResult.error("0", "密码错误！", null);
        }
        UpdateWrapper up = new UpdateWrapper();
        if (!StringUtil.isEmpty(memberPwdReq.getNewPassWord())) {
            String salt = oConvertUtils.randomGen(8);
            String password = PasswordUtil.encrypt(phone, memberPwdReq.getNewPassWord(), salt);
            up.set("password", password);
            up.set("salt", salt);
        }

        up.eq("id", bikeMemberUser.getId());
        int param = memberMapper.update(null, up);
        if (param == 1) {
            return BikeResult.ok("1", "修改成功", null);
        } else {
            return BikeResult.error("0", "修改失败", null);
        }
    }

}
